﻿using QuickGraph;
using System;
using System.Collections.Generic;

namespace InteractiveFiction.Model
{
    public enum Direction {North, South, East, West, NorthEast, NorthWest, SouthEast, SouthWest, Up, Down, In, Out }

    /// <summary>
    /// The path between two parts of the story world.
    /// </summary>
    public class StoryEdge : IEdge<StoryNode>
    {
        public StoryEdge(StoryNode source, StoryNode target, Direction directionToTarget)
        {
            Source = source;
            Target = target;
            DirectionToTarget = directionToTarget;
            _historyGuards = new LinkedList<StoryEdge>();
            _inventoryGuards = new LinkedList<StoryItem>();
        }

        public StoryNode Source { get; private set; }
        public StoryNode Target { get; private set; }
        public Direction DirectionToTarget { get; private set; }
        public string DenialMessage { get; private set; } //A message which is displayed when you aren't allowed to transverse the edge
        public StoryNode Redirect { get; private set; } //Optional node which you can be redirected to if you aren't allowed to transverse the edge

        private ICollection<StoryEdge> _historyGuards; // You must have already passed along these edges in order to pass along this one
        private ICollection<StoryItem> _inventoryGuards; // You must also be carrying these items in order to cross

        /// <summary>
        /// Is this character allowed to cross this edge?
        /// </summary>
        /// <param name="transverser"></param>
        /// <returns></returns>
        public bool AllowedToTransverse(Character transverser)
        {
            if (transverser.Location != Source)
                return false; // The character is in the wrong place

            int edgesPassed = 0;
            foreach (StoryEdge edge in transverser.History)
            {
                foreach (StoryEdge guard in _historyGuards)
                {
                    if (edge == guard)
                        edgesPassed++;
                }
            }
            if (edgesPassed > _historyGuards.Count || edgesPassed > transverser.History.Count)
                throw new Exception("More edge guards passed than exist.");

            int itemsPassed = 0;
            foreach (StoryItem item in transverser.Inventory)
            {
                foreach (StoryItem guard in _inventoryGuards)
                {
                    if (item == guard)
                        itemsPassed++;
                }
            }
            if (itemsPassed > _inventoryGuards.Count || itemsPassed > transverser.Inventory.Count)
                throw new Exception("More item guards passed than exist.");


            return edgesPassed == _historyGuards.Count && itemsPassed == _inventoryGuards.Count;
        }

        public void AddGuard(StoryEdge edgeGuard)
        {
            _historyGuards.Add(edgeGuard);
        }

        public void AddGuard(StoryItem itemGuard)
        {
            _inventoryGuards.Add(itemGuard);
        }

    }
}